/*
 * bomb.c
 *
 *  Created on: 2013
 *      Author: Eddy Zogbo, Moncef Sbay
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stddef.h>
#include <SDL.h>
#include <SDL_image.h>

#include "../include/game.h"
#include "../include/misc.h"
#include "../include/bomb.h"
#include "../include/monster_list.h"

struct s_bomb {
	int x, y, power, life_time, has_exploded;//place, power, duration, check if it has exploded
	Uint32 time;
	SDL_Surface * directed_img[5];
	enum e_state current_state;
};

t_bomb set_bomb(int x, int y, t_player player) {
	assert(player);
	t_bomb bomb = malloc(sizeof(*bomb));
	if (!bomb)
		error("Memory error");
	bomb->directed_img[0] = load_image(IMG_BOMB_TTL1);
	bomb->directed_img[1] = load_image(IMG_BOMB_TTL2);
	bomb->directed_img[2] = load_image(IMG_BOMB_TTL3);
	bomb->directed_img[3] = load_image(IMG_BOMB_TTL4);
	bomb->directed_img[4] = load_image(IMG_BOMB_TTL5);
	bomb->current_state = time_4;
	bomb->has_exploded = 0;
	bomb->power = player_get_bomb_range(player);
	bomb->life_time = BOMB_LIFETIME;
	bomb->time = SDL_GetTicks();
	bomb->x = x;
	bomb->y = y;
	return bomb;
}

void bomb_set_current_state(t_bomb bomb, enum e_state state) {
	assert(bomb);
	bomb->current_state = state;
}

void bomb_dec_time(t_bomb bomb) {
	assert(bomb);
	bomb->life_time -= 1;
}

void state_display(t_bomb bomb, enum e_state state) {
	assert(bomb);
	bomb->current_state = state;
}

void explode_bomb(t_bomb bomb) {
	assert(bomb);
	bomb->has_exploded = 1;
}

int has_exploded(t_bomb bomb) {
	return bomb->has_exploded;
}

int bomb_get_power(t_bomb bomb) {
	return bomb->power;
}

//spread the bomb and check all the effect
void bomb_spreading(t_bomb bomb, t_map map, t_player player,
		t_monster_list monster_list, SDL_Surface *screen) {

	assert(bomb);
	assert(screen);
	assert(map);
	assert(player);
	assert(monster_list);

	int x = bomb->x;
	int y = bomb->y;

	SDL_Rect place;
	place.x = x * SIZE_BLOC;
	place.y = y * SIZE_BLOC;

	SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
			&place);
	monster_list_kill(x, y, monster_list);//check if there is a monster to be killed
	int up, down, right, left, power;//spread the bomb in the four directions
	power = bomb->power;
	up = 1;
	down = 1;
	right = 1;
	left = 1;

	while (map_is_inside(map, x + right, y) && bomb_can_explode(map, x + right,
			y) && right <= power) {
		SDL_Rect place;
		place.x = (x + right) * SIZE_BLOC;
		place.y = y * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
		monster_list_kill(x + right, y, monster_list);//check if there is a monster to be killed in the right direction
		right += 1;
	}

	while (map_is_inside(map, x - left, y)
			&& bomb_can_explode(map, x - left, y) && left <= power) {
		SDL_Rect place;
		place.x = (x - left) * SIZE_BLOC;
		place.y = y * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
		monster_list_kill(x - left, y, monster_list);
		left += 1;
	}

	while (map_is_inside(map, x, y - up) && bomb_can_explode(map, x, y - up)
			&& up <= power) {
		SDL_Rect place;
		place.x = x * SIZE_BLOC;
		place.y = (y - up) * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
		up += 1;
	}

	while (map_is_inside(map, x, y + down)
			&& bomb_can_explode(map, x, y + down) && down <= power) {
		SDL_Rect place;
		place.x = x * SIZE_BLOC;
		place.y = (y + down) * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
		monster_list_kill(x, y + down, monster_list);
		down += 1;
	}
}
//it is the second explosion(boom..boom) and display the bonus if there is one
void bomb_spreading1(t_bomb bomb, t_map map, t_player player,
		t_monster_list monster_list, SDL_Surface *screen) {

	assert(bomb);
	assert(screen);
	assert(map);
	assert(player);
	assert(monster_list);

	int x = bomb->x;
	int y = bomb->y;

	SDL_Rect place;
	place.x = x * SIZE_BLOC;
	place.y = y * SIZE_BLOC;

	SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
			&place);

	if (player_get_x(player) == x && player_get_y(player) == y) {
		player_dec_nb_life(screen, player);
	}
	monster_list_kill(x, y, monster_list);

	int up, down, right, left, power;
	power = bomb->power;
	up = 1;
	down = 1;
	right = 1;
	left = 1;

	while (map_is_inside(map, x + right, y) && bomb_can_explode(map, x + right,
			y) && right <= power) {
		SDL_Rect place_right;
		place_right.x = (x + right) * SIZE_BLOC;
		place_right.y = y * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place_right);
		if (player_get_x(player) == x + right && player_get_y(player) == y) {
			player_dec_nb_life(screen, player);
		}
		monster_list_kill(x + right, y, monster_list);
		if (map_get_cell_type(map, x + right, y) == CELL_CASE) {
			int shift_type = map_get_cell_shift_type(map, x + right, y);
			int new_type = (shift_type << 4) | CELL_BONUS;
			if (shift_type == BONUS_MONSTER) {
				list_add_M(monster_list, monster_place(x + right, y));
			}
			map_set_cell_type(map, x + right, y, new_type);
		}

		right += 1;
	}

	while (map_is_inside(map, x - left, y)
			&& bomb_can_explode(map, x - left, y) && left <= power) {
		SDL_Rect place_left;
		place.x = (x - left) * SIZE_BLOC;
		place.y = y * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place_left);
		if (player_get_x(player) == x - left && player_get_y(player) == y) {
			player_dec_nb_life(screen, player);
		}
		monster_list_kill(x - left, y, monster_list);
		if (map_get_cell_type(map, x - left, y) == CELL_CASE) {
			int subtype = map_get_cell_shift_type(map, x - left, y);
			int new_type = (subtype << 4) | CELL_BONUS;
			if (subtype == BONUS_MONSTER) {
				list_add_M(monster_list, monster_place(x - left, y));
			}
			map_set_cell_type(map, x - left, y, new_type);
		}
		left += 1;
	}

	while (map_is_inside(map, x, y - up) && bomb_can_explode(map, x, y - up)
			&& up <= power) {
		SDL_Rect place_up;
		place.x = x * SIZE_BLOC;
		place.y = (y - up) * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place_up);
		if (player_get_x(player) == x && player_get_y(player) == y - up) {
			player_dec_nb_life(screen, player);
		}
		monster_list_kill(x, y - up, monster_list);
		if (map_get_cell_type(map, x, y - up) == CELL_CASE) {
			int subtype = map_get_cell_shift_type(map, x, y - up);
			int new_type = (subtype << 4) | CELL_BONUS;
			if (subtype == BONUS_MONSTER) {
				list_add_M(monster_list, monster_place(x, y - up));
			}
			map_set_cell_type(map, x, y - up, new_type);
		}
		up += 1;
	}

	while (map_is_inside(map, x, y + down)
			&& bomb_can_explode(map, x, y + down) && down <= power) {
		SDL_Rect place_down;
		place_down.x = x * SIZE_BLOC;
		place_down.y = (y + down) * SIZE_BLOC;

		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place_down);
		if (player_get_x(player) == x && player_get_y(player) == y + down) {
			player_dec_nb_life(screen, player);
		}
		monster_list_kill(x, y + down, monster_list);
		if (map_get_cell_type(map, x, y + down) == CELL_CASE) {
			int subtype = map_get_cell_shift_type(map, x, y + down);
			int new_type = (subtype << 4) | CELL_BONUS;
			if (subtype == BONUS_MONSTER) {
				list_add_M(monster_list, monster_place(x, y + down));
			}
			map_set_cell_type(map, x, y + down, new_type);
		}
		down += 1;
	}
}

void bomb_display(t_bomb bomb, t_map map, t_player player,
		t_monster_list monster_list, SDL_Surface *screen) {
	assert(bomb);
	assert(screen);
	assert(map);
	assert(player);
	assert(monster_list);

	SDL_Rect place;
	place.x = bomb->x * SIZE_BLOC;
	place.y = bomb->y * SIZE_BLOC;

	Uint32 diff = (SDL_GetTicks() - bomb->time);//the bomb state is going to change till the explosion
	if (diff < 1000) {
		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
	}

	else if (diff > 1000 && diff < 2000) {
		state_display(bomb, time_3);
		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
	} else if (diff > 2000 && diff < 3000) {
		state_display(bomb, time_2);
		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
	} else if (diff > 3000 && diff < 4000) {
		state_display(bomb, time_1);
		SDL_BlitSurface(bomb->directed_img[bomb->current_state], NULL, screen,
				&place);
	} else if (diff > 4000 && diff < 5000) {
		state_display(bomb, time_5);
		bomb_spreading(bomb, map, player, monster_list, screen);
	} else {
		bomb_spreading1(bomb, map, player, monster_list, screen);
		explode_bomb(bomb);//the bomb has exploded it can be delete of the bomb_list
	}
}
//check if the bomb can explode in (x,y)
int bomb_can_explode(t_map map, int x, int y) {
	assert(map);
	switch (map_get_cell_type(map, x, y)) {

	case CELL_SCENERY:
		return 0;
		break;
	case CELL_DOOR:
		return 0;
		break;
	case CELL_CLOSED_DOOR:
		return 0;
		break;
	default:
		return 1;
	}
}



